import {
    Connection,
    FieldInfo,
    MysqlError,
} from 'mysql';

import { DB } from '../config/Config';
import BaseEntity from '../entity/BaseEntity';
import DataEntity from '../entity/DataEntity';
import DbUtils from '../utils/DbUtils';

/**
 * dao基础类
 */
export default abstract class BaseDao<T extends BaseEntity> {
    /**
     * 获取数据库链接
     */
    protected getConn(): Connection {
        return DbUtils.init(DB);
    }
    /**
     * 获取要操作的实体表名
     */
    protected abstract getTableName(): string;
    /**
     * 创建新的实体
     */
    protected abstract newInsance(): T;
    /**
     * 保存数据
     * @param data 要保存的数据
     */
    save(data: T): Promise<unknown> {
        let conn = this.getConn();
        return new Promise((resolve, reject) => {
            conn.query('INSERT INTO ' + this.getTableName() + ' SET ?', data, function (err: MysqlError | null, results?: any, fields?: FieldInfo[]) {
                if (err) {
                    throw err
                };
                resolve({
                    err, results, fields
                });
            });
        }).finally(() => {
            conn.end();
        })
    }
    /**
     * 更新数据
     */
    update<K extends DataEntity>(data: K, fileds: string[]): Promise<unknown> {
        let conn = this.getConn();
        return new Promise((resolve, reject) => {
            let sql = 'UPDATE ' + this.getTableName() + ' SET ';
            let values: any[] = [];
            fileds.forEach((filed, index) => {
                if (index > 0) {
                    sql += ',';
                }
                sql += filed + '=?';
                let value: any = null;
                for (const key in data) {
                    if (key === filed) {
                        value = data[key];
                    }
                }
                values.push(value);
            })
            values.push(data.id);
            conn.query(sql + ' where _id=?', values, function (err: MysqlError | null, results?: any, fields?: FieldInfo[]) {
                if (err) {
                    throw err
                };
                resolve({
                    err, results, fields
                });
            });
        }).finally(() => {
            conn.end();
        })
    }
    /**
     * 删除数据
     * @param data 
     * @returns 
     */
    deleteData<K extends DataEntity>(id: Number): Promise<unknown> {
        let conn = this.getConn();
        return new Promise((resolve, reject) => {
            conn.query('DELETE FROM  ' + this.getTableName() + ' where _id=?', [id], function (err: MysqlError | null, results?: any, fields?: FieldInfo[]) {
                if (err) {
                    throw err
                };
                resolve({
                    err, results, fields
                });
            });
        }).finally(() => {
            conn.end();
        })
    }
    /**
     * 查询数据
     */
    async get<K extends DataEntity>(id: Number): Promise<K | null> {
        let conn = this.getConn();
        return await new Promise<K | null>((resolve, reject) => {
            conn.query('select * FROM  ' + this.getTableName() + ' where _id=?', [id], (err: MysqlError | null, results?: any, fields?: FieldInfo[]) => {
                if (err) {
                    throw err
                };
                if (!results || results === null || results.length <= 0) {
                    resolve(null);
                } else {
                    resolve(Object.assign(this.newInsance(), results[0]));
                }
            });
        }).then().finally(() => {
            conn.end();
        })
    }
}
